﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Windows.Forms;

namespace ENG.EngStartQueue.Bindings
{
  public class Binder
  {
    public struct BindInfo:IComparable<BindInfo>
    {
      public enum eDirection
      {
        FromObject = 2,
        ToObject = 4,
        Both = FromObject | ToObject
      }

      public readonly string MemberName;
      public readonly string ControlName;
      public readonly string ControlPropertyName;
      public readonly eDirection Direction;

      public BindInfo(string memberName, string controlName, string controlPropertyName) :
        this (memberName, controlName, controlPropertyName, eDirection.Both) { }
      public BindInfo(string memberName, string controlName, string controlPropertyName, eDirection direction)
      {
        this.MemberName = memberName;
        this.ControlName = controlName;
        this.ControlPropertyName = controlPropertyName;
        this.Direction = direction;
      }

      #region IComparable<BindInfo> Members

      public int CompareTo(BindInfo other)
      {
        int ret;
        ret = this.MemberName.CompareTo(other.MemberName);
        if (ret == 0)
          ret = this.ControlName.CompareTo(other.ControlName);
        if (ret == 0)
          ret = this.ControlPropertyName.CompareTo(other.ControlPropertyName);
        return ret;
      }

      #endregion
    }
    private List<BindInfo> Bindings = new List<BindInfo>();

    public void Bind(string memberName, string controlName, string controlPropertyName)
    {
      Bind(memberName, controlName, controlPropertyName, BindInfo.eDirection.Both);
    }
    public void Bind(string memberName, string controlName, string controlPropertyName, BindInfo.eDirection direction)
    {
      BindInfo bi = new BindInfo(memberName, controlName, controlPropertyName, direction);

      Bindings.Add(bi);
    }
    public BindInfo[] GetCurrentBindings()
    {
      return
        Bindings.ToArray();
    }
    public void Clear() 
    {
      Bindings.Clear();
    }
    public void Unbind(BindInfo bindInfo)
    {
      Bindings.Remove(bindInfo);
    }
    public void Unbind(int index)
    {
      Bindings.RemoveAt(index);
    }

    public void Update(object source, System.Windows.Forms.Control target)
    {
      foreach (var fItem in Bindings)
      {
        Update(fItem, source, target);
      } // foreach (var fItem in Bindings)
    }

    private void Update (BindInfo bi,object source, System.Windows.Forms.Control target)
    {
      if (0 == (bi.Direction & BindInfo.eDirection.FromObject))
        return;

      Type objectType = source.GetType();
      object val;

      val = objectType.InvokeMember(
        bi.MemberName, BindingFlags.GetField | BindingFlags.GetProperty, null, source, null);

      Control control =
        target.Controls[bi.ControlName];
      Type controlType = control.GetType();
      controlType.InvokeMember(
        bi.ControlPropertyName, BindingFlags.SetProperty, null, control, new object[] { val });
    }
    private void Update(BindInfo bi, System.Windows.Forms.Control source, object target)
    {
      if (0 == (bi.Direction & BindInfo.eDirection.ToObject))
        return;

      Control control =
        source.Controls[bi.ControlName];
      Type controlType = control.GetType();
      object val = controlType.InvokeMember(
        bi.ControlPropertyName, BindingFlags.GetProperty, null, control, null);

      Type objectType = target.GetType();
      objectType.InvokeMember(
        bi.MemberName, BindingFlags.SetProperty | BindingFlags.SetField, null, target, new object[] { val });
    }

    public void Update(System.Windows.Forms.Control source, object target)
    {
      foreach (var fItem in Bindings)
      {
        Update(fItem, source, target);
      } // foreach (var fItem in Bindings)
    }

  }
}
